
function ms_out = mismatch_shaping(pdm_in ,bitlevel, miss_en ,shap_en,mismatch_shaping_level,isi_err_en,isi_err_shap_en,function_sel,testNO)
% bitlevel = 4;
% pdm_in = [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7];
%% 失配计算
    if(miss_en~="enable" && shap_en~="enable")
        ms_out = pdm_in';
    else
        if(miss_en=="enable")
            % randomNums = generateZeroMeanRand(2^(bitlevel)-1,mismatch_shaping_level,1000);
            % randomNums = randomNums';
            if(mismatch_shaping_level == "worst")
                % randomNums = [0.00150477,0.00151202,0.00151719,0.00153787,0.00154143,0.00158805,0.00161778,0.00164016,0.00166533,0.0016844,0.00170297,0.00171104,0.00171955,0.0017615,0.00192122,0.00196962,-0.00197787,-0.00197131,-0.00191989,-0.00190245,-0.00187989,-0.00185351,-0.00183404,-0.00182914,-0.00181099,-0.0016774,-0.00164328,-0.00158054,-0.001579,-0.00157438,-0.00156121];
                randomNums = [0.00150477, -0.00151202, 0.00151719, -0.00183787, -0.00154143, 0.00158805, -0.00161778, -0.00135984, -0.00166533, 0.0016844, 0.00170297, 0.00144654, -0.00171955, 0.0017615, -0.00192122, 0.00196962                ];
                % randomNums = [0.00151202,-0.00157438,0.00166533,-0.00164328,-0.00190245,0.00192122,-0.00197787,0.00171104,0.00170297,-0.00181099,0.00154143,0.00150477,0.0016844,0.00171955,-0.00156121,0.0017615,0.00196962,-0.00197131,0.00151719,-0.00158054,-0.00182914,-0.0016774,0.00158805,-0.00191989,-0.001579,0.00153787,-0.00185351,-0.00183404,0.00164016,-0.00187989,0.00161778];
            else
                if(mismatch_shaping_level == "best")
                    randomNums = [-0.001035355,0.000873645,-0.000977355,0.000932645,-0.001031355,0.000888645,0.000838645,0.000912645,-0.001050355,-0.000988355,-0.001016355,0.000847645,0.000917645,0.000876645,-0.001001355,-0.000975355,-0.000964355,0.000900645,0.000884645,0.000925645,-0.001920355,-0.001023355,-0.000985355,0.000862645,0.000845645,0.000931645,0.000843645,-0.000996355,-0.001007355,0.000853645,0.000836645];
                else
                    error("Mismatch Param Set Error");
                end
            end
        else
            randomNums = zeros(1,2^(bitlevel));
        end
    %% 将PDM码转成温度计码

        dac_data = zeros(length(pdm_in),2^(bitlevel));
        temp_code = 2^(bitlevel-1) + pdm_in;
        temp_code = temp_code';
        temp_code = 2.^temp_code -1;

        dwa_point_start = 0;
        dwa_point_end   = 0;

        for i=1:2^(bitlevel)
            dac_data(:,i) = 2^(i-1);
            dac_data(:,i) = (bitand(temp_code(:,1) , dac_data(:,i)) ~= 0);
        end
        [dac_data_line_len ,dac_data_row_len] = size(dac_data);

if(function_sel == "old")
        if(shap_en=="enable")
            for i=1 : length(pdm_in)
                line_sum = sum(dac_data(i, :));

                dwa_data = zeros(1,2^(bitlevel));

                %模加法
                dwa_point_end    = dwa_point_start + line_sum;
                dwa_point_start  = dwa_point_start + 1;
                if(dwa_point_end   > 2^(bitlevel))  dwa_point_end   = dwa_point_end   - (2^(bitlevel)); end
                if(dwa_point_start > 2^(bitlevel))  dwa_point_start = dwa_point_start - (2^(bitlevel)); end


                if(dwa_point_end < dwa_point_start) % 跨边界输出
                    dwa_data(dwa_point_start:2^(bitlevel)) = 1;
                    dwa_data(1:dwa_point_end)  = 1;
                else
                    dwa_data(dwa_point_start:dwa_point_end) = 1;
                end

                dac_data(i,:) = dwa_data;
                dwa_point_start = dwa_point_end;
            end
        end

        if(isi_err_shap_en=="enable")
            for i=2:dac_data_line_len
                isi_gamma    = dac_data(i,:) - dac_data(i-1,:);
                isi_err      = isi_gamma -0.5;
                isi_feedback = dac_data(i,:) + isi_err;
                isi_weight   = isi_feedback .*(0.75-dac_data(i-1,:));
                [isi_weight, originalIndices] = sort(isi_weight, 'descend');
                isi_outsum   = sum(dac_data(i,:));
                for l=1:dac_data_row_len
                    isi_outsum = isi_outsum - 1;
                    if(isi_outsum >=0 )
                        dac_data(i,originalIndices(l)) = 1;
                    else
                        dac_data(i,originalIndices(l)) = 0;
                    end

                end
            end
        end

else


        [dac_data,~]=MMS_16DAC(dac_data,testNO);
end
        if(isi_err_en=="enable")
            mismatch_ratio = 0.01;
            A00_nom = 0.00;
            A01_nom = -0.050;
            A10_nom = 0.055;
%             A01_nom = 0;
%             A10_nom = 0;
            A11_nom = -0.000;
            isi_params(2^bitlevel) = struct('A00', A00_nom, 'A01', A01_nom, 'A10', A10_nom, 'A11', A11_nom);
            fprintf('启用元件失配模拟（失配比例: %.0f%%）\n', mismatch_ratio*100);
            for i = 1:2^bitlevel
                isi_params(i).A00 = A00_nom ;%* (1 + mismatch_ratio * (2*rand() - 1));
                isi_params(i).A01 = A01_nom ;%* (1 + mismatch_ratio * (2*rand() - 1));
                isi_params(i).A10 = A10_nom ;%* (1 + mismatch_ratio * (2*rand() - 1));
                isi_params(i).A11 = A11_nom ;%* (1 + mismatch_ratio * (2*rand() - 1));
            end
            for i = 1:dac_data_row_len
                dac_data_row_data = dac_data(:,i);
                for(l=2:dac_data_line_len)
                    if(dac_data(l,i) == 1 && dac_data(l-1,i)==0)
                        dac_data_row_data(l) = dac_data(l,i) + isi_params(i).A01;
                    end
                    if(dac_data(l,i) == 0 && dac_data(l-1,i)==1)
                        dac_data_row_data(l) = dac_data(l,i) + isi_params(i).A10;
                    end
                    if(dac_data(l,i) == 1 && dac_data(l-1,i)==1)
                        dac_data_row_data(l) = dac_data(l,i) + isi_params(i).A11;
                    end
                end
                dac_data(:,i) = dac_data_row_data;
            end



        end

        dac_data_randomNums = dac_data .*randomNums;
        dac_data = dac_data + dac_data_randomNums;

        ms_out = sum(dac_data,2);
        ms_out = (ms_out  -2^(bitlevel-1))/2.65;
    end


end

function [sv_out, switch_count] = MMS_16DAC(A, L_target)
    % 文档MMS算法MATLAB实现：16路电流舵DAC温度计码失配整形
    % 输入：
    %   A: (N,16) 温度计码矩阵，每行16个0/1，对应16个DAC单元输入（-8~7范围）
    %   L_target: 目标切换数量（文档建议4~6，平衡ISI抑制与复杂度）
    % 输出：
    %   sv_out: (N,16) 整形后DAC单元控制信号（0/1），抑制静态失配与ISI
    %   switch_count: (N,1) 每周期实际切换元件数

    [N, M] = size(A);
    if M ~= 16
        error('输入矩阵必须为N×16（16个DAC单元）');
    end

    sy_max = 0;
    sy_min = 0;

    % 初始化参数（文档图10/L逻辑）
    sv_out = zeros(N, 16);          % 整形后输出
    switch_count = zeros(N, 1);     % 切换计数
    sy = zeros(1, 16);              % 元件优先级权重（初始均匀）
    sv_prev = zeros(1, 16);         % 上一周期DAC状态（初始全关）
    persent_prev = -1;
    for n = 1:N
        persent = fix(n/N*100);
        if(mod(persent,5)==0)

            if(persent_prev ~= persent)
                %clc;
                fprintf("mms处理中,进度%02d %%.\n",persent);
            end
        end
        persent_prev = persent;
        % 1. 读取当前周期温度计码对应的目标导通数v(n)（文档式7-9核心）
        v_curr = sum(A(n, :));  % 温度计码中1的个数即目标导通数（0~16）
        v_prev = sum(sv_prev);  % 上一周期导通数

        % 2. 计算on/off/rem（文档式10-12）
        delta_v = v_curr - v_prev;
        on = (L_target + delta_v) / 2;
        off = (L_target - delta_v) / 2;
        rem = (v_curr + v_prev - L_target) / 2;

        % 3. 边界修正（避免负数值，文档算法步骤2）
        if on < 0
            on = 0;
            off = L_target;
            rem = v_curr;
        elseif off < 0
            off = 0;
            on = L_target;
            rem = v_prev;
        elseif rem < 0
            rem = 0;
            on = v_curr;
            off = v_prev;
        end
        % 确保整数（实际硬件为整数切换）
        on = round(on);
        off = round(off);
        rem = round(rem);

        % 4. 元件选择（文档算法步骤3-4，基于部分排序的sy权重）
        % 4.1 从当前关闭的元件中，选on个sy最大的开启
        off_elements = find(sv_prev == 0);
        [~, off_idx] = sort(sy(off_elements), 'descend');
        if(max(sy) > sy_max)
            sy_max = max(sy);
        end
        if(min(sy) > sy_min)
            sy_min = min(sy);
        end
        select_on = off_elements(off_idx(1:min(on, length(off_elements))));

        % 4.2 从当前开启的元件中，关off个sy最小的
        on_elements = find(sv_prev == 1);
        [~, on_idx] = sort(sy(on_elements));
        select_off = on_elements(on_idx(1:min(off, length(on_elements))));

        % 4.3 确定当前周期状态（rem个持续导通+新开启-新关闭）
        sv_curr = sv_prev;
        sv_curr(select_on) = 1;
        sv_curr(select_off) = 0;
        % 强制修正：确保导通数等于v_curr（避免边界修正偏差）
        curr_on_count = sum(sv_curr);
        if curr_on_count < v_curr
            add_elements = setdiff(off_elements, select_on);
            sv_curr(add_elements(1:(v_curr - curr_on_count))) = 1;
        elseif curr_on_count > v_curr
            del_elements = setdiff(on_elements, select_off);
            sv_curr(del_elements(1:(curr_on_count - v_curr))) = 0;
        end

        % 5. 更新优先级权重sy（模拟失配整形，文档H2(z)噪声整形逻辑）
        sy = sy + sv_curr;  % 导通元件权重累加，避免重复使用（类似DWA旋转）
        [~,idx_t] = sort(sy);
        for i=1 :length(idx_t)
            sy(idx_t(i)) = i;
        end
%         sy = sy - min(sy);

        % 6. 记录输出与切换数
        sv_out(n, :) = sv_curr;
        switch_count(n) = length(select_on) + length(select_off);

        % 7. 更新上一周期状态
        sv_prev = sv_curr;
    end
end





function [sv_out, switch_count] = MMS_16DAC_modify(v_seq, L_target)
    % 文档MMS算法MATLAB实现：16路电流舵DAC失配整形（修正版）
    % 输入：
    %   v_seq: (N,1) ΔΣ调制器输出序列（0~16，对应16个DAC单元的目标导通数）
    %   L_target: 目标切换数量（文档建议4~6，平衡ISI抑制与复杂度）
    % 输出：
    %   sv_out: (N,16) 整形后DAC单元控制信号（0/1），抑制静态失配与动态切换误差
    %   switch_count: (N,1) 每周期实际切换元件数

    % 输入校验
    [N, M] = size(v_seq);
    if M ~= 16
        error('输入矩阵必须为N×16（16个DAC单元）');
    end
%     if L_target < 1 || L_target > 16
%         error('L_target建议设置为4~6（参考论文Fig.10）');
%     end

    % 初始化参数（严格匹配论文算法步骤）
    sv_out = zeros(N, 16);          % 整形后DAC控制信号
    switch_count = zeros(N, 1);     % 实际切换元件数
    sy = 1:16;                      % 元件优先级权重（初始线性，支持部分排序）
    sv_prev = zeros(1, 16);         % 上一周期DAC状态（初始全关）
    persent_prev = -1;

    for n = 1:N
        % 进度打印（简化冗余逻辑）
        persent = fix(n/N*100);
        if mod(persent,5)==0 && persent_prev ~= persent
            fprintf("MMS处理中,进度%02d%%.\n",persent);
            persent_prev = persent;
        end

        % 1. 读取当前周期目标导通数v(n)（论文中v(n)为ΔΣ调制器输出，正整数）
        v_curr = v_seq(n);
        v_prev = sum(sv_prev);      % 上一周期实际导通数

        % 2. 计算on/off/rem（论文式10-12）
        delta_v = v_curr - v_prev;
        on = (L_target + delta_v) / 2;
        off = (L_target - delta_v) / 2;
        rem = (v_curr + v_prev - L_target) / 2;

        % 3. 边界修正（论文算法步骤2：重新调整L，避免负数值）
        L = L_target;  % 动态调整L，满足on/off/rem ≥ 0
        if on < 0
            on = 0;
            off = L;
            rem = v_curr;
        elseif off < 0
            off = 0;
            on = L;
            rem = v_prev;
        elseif rem < 0
            L = v_curr + v_prev;    % 重新选择L，使rem=0
            on = v_curr;
            off = v_prev;
            rem = 0;
        end
        % 硬件整数约束（四舍五入，匹配实际电路）
        on = round(on);
        off = round(off);
        rem = round(rem);

        % 4. 元件选择（论文算法步骤3-4：基于sy权重的部分排序）
        % 4.1 从关闭元件中选on个sy最大的开启
        off_elements = find(sv_prev == 0);
        [~, off_idx] = sort(sy(off_elements), 'descend');
        select_on = off_elements(off_idx(1:min(on, length(off_elements))));
        % 4.2 从开启元件中选off个sy最小的关闭
        on_elements = find(sv_prev == 1);
        [~, on_idx] = sort(sy(on_elements));
        select_off = on_elements(on_idx(1:min(off, length(on_elements))));

        % 5. 确定当前周期DAC状态（强制匹配目标导通数v_curr）
        sv_curr = sv_prev;
        sv_curr(select_on) = 1;
        sv_curr(select_off) = 0;
        % 修正导通数偏差（避免边界修正后的误差）
        curr_on_count = sum(sv_curr);
        if curr_on_count < v_curr
            add_elements = setdiff(off_elements, select_on);
            add_num = min(v_curr - curr_on_count, length(add_elements));
            sv_curr(add_elements(1:add_num)) = 1;
        elseif curr_on_count > v_curr
            del_elements = setdiff(on_elements, select_off);
            del_num = min(curr_on_count - v_curr, length(del_elements));
            sv_curr(del_elements(1:del_num)) = 0;
        end

        % 6. 权重更新（论文一阶失配整形：元素旋转/DWA，H2(z)=1-z^-1）
        used_elements = find(sv_curr == 1);
        sy(used_elements) = sy(used_elements) + 1;  % 导通元件权重累加
        sy = circshift(sy, 1);                      % 元素旋转，避免重复使用

        % 7. 记录输出与实际切换数（基于异或运算，统计真实切换量）
        sv_out(n, :) = sv_curr;
        switch_count(n) = sum(xor(sv_curr, sv_prev));

        % 8. 更新上一周期状态
        sv_prev = sv_curr;
    end
end







function randomNums = generateZeroMeanRand(numPoints, maxValue, maxIter, tolerance)
    % 生成均值为0、最大值可设置的随机数
    % 输入：
    %   numPoints: 随机数数量（必须≥2）
    %   maxValue:  允许的最大值（正数）
    %   maxIter:   最大迭代次数（默认100）
    %   tolerance: 均值容差（默认1e-6）
    % 输出：
    %   randomNums: 满足条件的随机数数组

        % 参数校验与默认值设置
        if nargin < 3 || isempty(maxIter), maxIter = 100; end
        if nargin < 4 || isempty(tolerance), tolerance = 1e-4; end
        assert(numPoints >= 2, '随机数数量至少为2');
        assert(maxValue > 0, '最大值必须为正数');

        % 生成初始正态分布随机数（均值为0）
        randomNums = randn(numPoints, 1);  % 标准正态分布

        % 迭代调整最大值和均值
        for iter = 1:maxIter
            % 计算当前最大值并缩放至目标范围
            currentMax = max(abs(randomNums));
            scaleFactor = maxValue / currentMax;
            randomNums = randomNums * scaleFactor;

            % 调整均值归零（不改变数据范围）
            currentMean = mean(randomNums);
            randomNums = randomNums - currentMean;

            % 检查均值是否满足容差
            if abs(mean(randomNums)) < tolerance
                break;
            end
        end

        % 验证结果
        finalMax = max(abs(randomNums));
        finalMean = mean(randomNums);
        fprintf('生成完成: 数量=%d, 实际最大值=%.4f, 实际均值=%.6f, 迭代次数=%d\n',...
                numPoints, finalMax, finalMean, min(iter, maxIter));
end


